import { useParams } from 'react-router-dom';
import { useState, useEffect, useRef } from 'react';
import Client from '../../utils/ossClient';
import { Row, Col, Layout, Spin, message } from 'antd';
import axios from 'axios';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';
import * as THREE from 'three';
const { Content } = Layout;

export default () => {
  const clock = new THREE.Clock();
  let params = useParams();
  let client = Client();
  let ref = useRef();
  const [loading, SetLoading] = useState(false);
  let raycaster = new THREE.Raycaster();
  let mouse = new THREE.Vector2();
  let events = {
    start: [],
    update: [],
    click: {},
  };
  useEffect(() => {
    const sceneLoader = new THREE.ObjectLoader();
    SetLoading(true);
    let url = 'model/' + params.fileName + '.json';
    let temp = 'model/1652539651520_admin_.json';
    let url1 = client.signatureUrl(url);
    axios.get(url1).then(res => {
      let data = res.data;
      const renderer = new THREE.WebGLRenderer({ antialias: true });
      renderer.physicallyCorrectLights = true;
      renderer.outputEncoding = THREE.sRGBEncoding;
      renderer.shadowMap.enabled = true;
      renderer.setSize(ref.current.offsetWidth, ref.current.offsetHeight);
      const camera = new THREE.PerspectiveCamera(
        45,
        ref.current.offsetWidth / ref.current.offsetHeight,
        0.01,
        10000
      );
      camera.position.z = 50;
      ref.current.appendChild(renderer.domElement);

      let controls = new OrbitControls(camera, renderer.domElement);
      controls.tag = 'helper';
      controls.target.set(0, 0, 0);
      controls.update();
      controls.enablePan = false;
      controls.enableDamping = true;

      let scene = sceneLoader.parse(data.scene);
      let scripts = data.scripts;
      let animations = [];
      let mixer = new THREE.AnimationMixer(scene);
      data.aniStr = JSON.parse(data.aniStr);
      for (let i = 0; i < data.aniStr.length; i++) {
        animations.push(THREE.AnimationClip.parse(data.aniStr[i]));
      }
      function getMousePosition(dom, x, y) {
        var rect = dom.getBoundingClientRect();
        return [(x - rect.left) / rect.width, (y - rect.top) / rect.height];
      }
      function getIntersects(point) {
        mouse.set(point.x * 2 - 1, -(point.y * 2) + 1);

        raycaster.setFromCamera(mouse, camera);

        const objects = [];

        scene.traverseVisible(function (child) {
          if (child.name == 'environment') {
            return;
          }
          objects.push(child);
        });

        return raycaster.intersectObjects(objects, false);
      }
      function onMouseDown(event) {
        //阻止触发dom默认事件
        event.preventDefault();
        //获取鼠标位置
        let array = getMousePosition(renderer.domElement, event.clientX, event.clientY);
        let onUpPosition = new THREE.Vector2(array[0], array[1]);
        const intersects = getIntersects(onUpPosition);
        console.log(intersects);
        for (let i = 0; i < intersects.length; i++) {
          let uuid = intersects[i].object.uuid;
          if (events.click[uuid] !== undefined) {
            for (let j = 0; i < events.click[uuid].length; i++) {
              events.click[uuid][j]();
            }
          }
        }
      }
      renderer.domElement.addEventListener('mousedown', onMouseDown, false);
      let scriptWrapResult = '{start:start,update:update,click:click}';
      for (var uuid in scripts) {
        let object = scene.getObjectByProperty('uuid', uuid);
        if (object === undefined) {
          message.warn('脚本无绑定对象 ' + uuid, 2);
          continue;
        }

        let cur = scripts[uuid];

        for (let i = 0; i < cur.length; i++) {
          let scriptInstance = cur[i];
          let functions = new Function(
            'scene,message,THREE,mixer,animations',
            scriptInstance.script + '\nreturn ' + scriptWrapResult + ';'
          ).bind(object)(scene, message, THREE, mixer, animations);

          for (let name in functions) {
            if (functions[name] === undefined) continue;

            if (events[name] === undefined) {
              continue;
            }
            if (name != 'click') events[name].push(functions[name].bind(object));
            else {
              if (events['click'][uuid] === undefined) events['click'][uuid] = [];

              events['click'][uuid].push(functions[name].bind(object));
            }
          }
        }
      }

      for (let i = 0; i < events.start.length; i++) {
        events.start[i]();
      }
      clock.start();
      function animation(time) {
        requestAnimationFrame(animation);

        controls.update();

        const delta = clock.getDelta();
        mixer.update(delta);

        for (let i = 0; i < events.update.length; i++)
          events.update[i](delta, clock.getElapsedTime());

        renderer.render(scene, camera);
      }
      console.log(res);
      SetLoading(false);
      animation();
    });
  }, []);
  return (
    <>
      <Layout>
        <Spin spinning={loading}>
          <Content style={{ padding: '5px 0px', backgroundColor: '#FAFAFA', height: '82vh' }}>
            <div style={{ height: '100%', width: '100%' }} ref={ref}></div>
          </Content>
        </Spin>
      </Layout>
    </>
  );
};
